using System.ComponentModel;
using System.Globalization;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Xsl;
using System.Net.Http.Headers;
using LinqToDB.Tools;
using LinqToDB.Common;

namespace NalogGarLoader.Model.NalogServices;

public class GarRequestFileListHelper 
{
    private static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();

    private const string GetAllDownloadFileInfoRequestBody = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:dow=\"https://fias.nalog.ru/WebServices/Public/DownloadService.asmx/\"><soapenv:Header/><soapenv:Body><dow:GetAllDownloadFileInfo/></soapenv:Body></soapenv:Envelope>";
    private const string DownloadServiceUri = @"https://fias.nalog.ru/WebServices/Public/DownloadService.asmx";
    private const string GetAllDownloadFileInfoSoapAction = @"https://fias.nalog.ru/WebServices/Public/DownloadService.asmx/GetAllDownloadFileInfo";

    public List<string> GetUpdates(DateOnly lastGarVersion)
    {
        log.Info($"Получение списка обновлений. Последняя дата обновления: {lastGarVersion}");

        var fileList = this.RequestFileList();
        SortedDictionary<DateOnly, string> downloadedFiles = [];

        foreach (var downloadFileInfo in fileList.Where(e => !string.IsNullOrEmpty(e.GarXMLDeltaURL) && e.GarVersion > lastGarVersion))
        {
            downloadedFiles.Add(downloadFileInfo.GarVersion, downloadFileInfo.GarXMLDeltaURL);
        }

        return [.. downloadedFiles.Values]; 
    }

    public string GetFullOnDate(DateOnly lastGarVersion)
    {
        log.Info($"Поиск полной выгрузки ГАР, ближайшей к {lastGarVersion}");

        var fileList = this.RequestFileList();

        NalogDownloadFileInfo? nalogDownloadFileInfo = fileList.Where(e => !string.IsNullOrEmpty(e.GarXMLFullURL) && e.GarVersion >= lastGarVersion).MinBy(e => e.GarVersion);

        if (nalogDownloadFileInfo == null)
            throw new WebException("Ошибка получения сведений о последне выгрузке ГАР: Сервис налоговой не предоставил информации.");

        return nalogDownloadFileInfo.GarXMLFullURL;
    }

    public string GetLatestFull()
    {
        //return GarRequestFileListHelper.LastFullGarUri; не работает

        log.Info($"Поиск последней полной выгрузки ГАР");

        var fileList = this.RequestFileList();

        NalogDownloadFileInfo? nalogDownloadFileInfo = fileList.Where(e => !string.IsNullOrEmpty(e.GarXMLFullURL)).MaxBy(e => e.GarVersion);

        if (nalogDownloadFileInfo == null)
            throw new WebException("Ошибка получения сведений о последне выгрузке ГАР: Сервис налоговой не предоставил информации.");

        return nalogDownloadFileInfo.GarXMLFullURL;        
    }    

    private List<NalogDownloadFileInfo> RequestFileList()
    {
        List<NalogDownloadFileInfo> downloadFileList = [];

        try
        {
            using HttpClient httpClient = new HttpClient(new HttpClientHandler { UseProxy = false });
            using var request = new HttpRequestMessage(HttpMethod.Post, GarRequestFileListHelper.DownloadServiceUri);
            request.Headers.Add("SOAPAction", GarRequestFileListHelper.GetAllDownloadFileInfoSoapAction);
            request.Content = new StringContent(GarRequestFileListHelper.GetAllDownloadFileInfoRequestBody, null, "text/xml");

            using var response = httpClient.Send(request);
            response.EnsureSuccessStatusCode();

            XmlSerializer xmlSerializer = new(typeof(GetAllDownloadFileInfoResponsesEnvelope));

            using (XmlReader xReader = XmlReader.Create(response.Content.ReadAsStream()))
            {
                var downloadFileInfoResponse = xmlSerializer.Deserialize(xReader) as GetAllDownloadFileInfoResponsesEnvelope;
                var downloadFileInfoArray = downloadFileInfoResponse?.Body?.GetAllDownloadFileInfoResponse?.GetAllDownloadFileInfoResult;

                if (downloadFileInfoArray != null)
                {
                    foreach (var downloadFileInfo in downloadFileInfoArray)
                    {
                        if (!string.IsNullOrWhiteSpace(downloadFileInfo.GarXMLDeltaURL)
                        || !string.IsNullOrWhiteSpace(downloadFileInfo.GarXMLFullURL))
                        {
                            downloadFileInfo.GarVersion = DateOnly.ParseExact(downloadFileInfo.VersionId, "yyyyMMdd", CultureInfo.InvariantCulture);

                            downloadFileList.Add(downloadFileInfo);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            log.Fatal(ex, "Исключение при запросе списка файлов от налоговой");
            throw;
        }

        return downloadFileList;
    }
}